home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / pascal / totsrc.zip / TOTLINK.PAS < prev    next >
Pascal/Delphi Source File  |  1991-02-11  |  34KB  |  1,228 lines

  1. {               Copyright 1991 TechnoJock Software, Inc.               }
  2. {                          All Rights Reserved                         }
  3. {                         Restricted by License                        }
  4.  
  5. {                             Build # 1.00                             }
  6.  
  7. Unit totLINK;
  8. {$I TOTFLAGS.INC}
  9.  
  10. {
  11.  Development Notes:
  12.  
  13. }
  14.  
  15. INTERFACE
  16.  
  17. Uses DOS,CRT,
  18.      totSTR;
  19.  
  20. Const
  21.   NoFiles: string[20] = 'No Files';
  22.  
  23. Type
  24.  
  25. tFileInfo = record
  26.      FileName: string[12];
  27.      Attr: byte;
  28.      Time: longint;
  29.      Size: longint;
  30.      LoadID: longint;
  31. end; {tFileInfo}
  32.  
  33. DLLNodePtr = ^DLLNodeObj;
  34. pDLLNodeOBJ = ^DLLNodeOBJ;
  35. DLLNodeOBJ = Object         {this object is not extensible}
  36.    vNextPtr: DLLNodePtr;
  37.    vPrevPtr: DLLNodePtr;
  38.    vDataPtr: pointer;
  39.    vSize: longint;
  40.    vStatus: byte;   {selectable, selected}
  41.    {methods...}
  42.    procedure FreeData;
  43.    function  NextPtr: DLLNodePtr;
  44.    function  PrevPtr: DLLNodePtr;
  45.    function  GetStatus(BitPos:byte): boolean;
  46.    procedure SetStatus(BitPos:byte;On:boolean);
  47.    function  GetStatusByte: byte;
  48.    procedure SetStatusByte(Val:byte); 
  49. end; {DLLNodeOBJ}
  50.  
  51. DLLPtr = ^DLLOBJ;
  52. pDLLOBJ = ^DLLOBJ;
  53. DLLOBJ = Object
  54.    vStartNodePtr:  DLLNodePtr;
  55.    vEndNodePtr:    DLLNodePtr;
  56.    vActiveNodePtr: DLLNodePtr;
  57.    vTotalNodes:       longint;
  58.    vActiveNodeNumber: longint;
  59.    vSortID:           shortInt;
  60.    vSortAscending:    boolean;
  61.    vSorted:           boolean;
  62.    vMaxNodeSize :     longint;
  63.    {methods...}
  64.    constructor Init;
  65.    function    Add(var TheData;Size:longint): integer;
  66.    function    Change(Node:DLLNodePtr;var TheData;Size:longint): integer;
  67.    function    InsertBefore(Node:DLLNodePtr;var TheData;Size:longint): integer;
  68.    procedure   Get(var TheData);
  69.    procedure   GetNodeData(Node:DLLNodePtr;Var TheData);
  70.    function    GetNodeDataSize(Node:DLLNodePtr):longint;
  71.    function    GetMaxNodeSize: longint;
  72.    procedure   Advance(Amount:longint);
  73.    procedure   Retreat(Amount:longint);
  74.    function    NodePtr(NodeNumber:longint): DLLNodePtr;
  75.    procedure   Jump(NodeNumber:longint);
  76.    procedure   ShiftActiveNode(NewNode: DLLNodePtr; NodeNumber: longint);
  77.    procedure   DelNode(Node:DLLNodePtr);
  78.    procedure   DelAllStatus(BitPos:byte;On:boolean);
  79.    function    TotalNodes: longint;
  80.    function    ActiveNodeNumber: longint;
  81.    function    ActiveNodePtr: DLLNodePtr;
  82.    function    StartNodePtr: DLLNodePtr;
  83.    function    EndNodePtr: DLLNodePtr;
  84.    procedure   EmptyList;
  85.    procedure   Sort(SortID:shortint;Ascending:boolean);
  86.    function    WrongOrder(Node1,Node2:DLLNodePtr;Asc:boolean): boolean; VIRTUAL;
  87.    procedure   SwapNodes(Node1,Node2:DLLNodePtr);                       VIRTUAL;
  88.    function    GetStr(Node:DLLNodePtr;Start,Finish: longint):string;    VIRTUAL;
  89.    destructor  Done;
  90. end; {DLLOBJ}
  91.  
  92. StrDLLPtr = ^StrDLLOBJ;
  93. pStrDLLOBJ = ^StrDLLOBJ;
  94. StrDLLOBJ = object (DLLOBJ)
  95.    {methods ...}
  96.    constructor Init;
  97.    function    Add(Str:string): integer;
  98.    function    Change(Node:DLLNodePtr;Str: string): integer;
  99.    function    InsertBefore(Node:DLLNodePtr;Str:string): integer;
  100.    function    WrongOrder(Node1,Node2:DLLNodePtr;Asc:boolean): boolean; VIRTUAL;
  101.    function    GetStr(Node:DLLNodePtr;Start,Finish: longint):string;    VIRTUAL;
  102.    destructor  Done;
  103. end; {StrDLLOBJ}
  104.  
  105. FileDLLPtr = ^FileDLLOBJ; 
  106. pFileDLLOBJ = ^FileDLLOBJ;
  107. FileDLLOBJ = object (DLLOBJ)
  108.    vFileMasks: string;
  109.    vFileAttrib: word;
  110.    {methods ...}
  111.    constructor Init;
  112.    procedure   FillList;
  113.    procedure   SetFileDetails(FileMasks:string; FileAttrib: word);
  114.    procedure   FillNewMask(FileMasks:string);
  115.    function    GetLongStr(Node:DLLNodePtr):string;
  116.    procedure   GetFileRecord(var FileInfo:tFileInfo; Item:longint);
  117.    function    GetFileMask:string;
  118.    function    WrongOrder(Node1,Node2:DLLNodePtr;Asc:boolean): boolean; VIRTUAL;
  119.    procedure   SwapNodes(Node1,Node2:DLLNodePtr);                       VIRTUAL;
  120.    function    GetStr(Node:DLLNodePtr;Start,Finish: longint):string;    VIRTUAL;
  121.    destructor  Done;
  122. end; {FileDLLOBJ}
  123.  
  124. function Subdirectory(B : byte):boolean;
  125. function FileAttribs(B:byte):string;
  126. function LongName(Info: tFileInfo):string;
  127. procedure LINKInit;
  128.  
  129. IMPLEMENTATION
  130. {|||||||||||||||||||||||||||||||||||||||||||||}
  131. {                                             }
  132. {     M i s c.  P r o c s   &   F u n c s     }
  133. {                                             }
  134. {|||||||||||||||||||||||||||||||||||||||||||||}
  135. function Subdirectory(B : byte):boolean;
  136. begin
  137.    Subdirectory := ((B and Directory) = Directory);
  138. end; {Subdirectory}
  139.  
  140. function FileAttribs(B:byte):string;
  141. var
  142.   S : string;
  143. begin
  144.    S := '    ';
  145.    If ((B and ReadOnly) = Readonly) then
  146.       S[1] := 'R';
  147.    If ((B and Hidden) = Hidden) then
  148.       S[2] := 'H';
  149.    If ((B and SysFile) = SysFile) then
  150.       S[3] := 'S';
  151.    If ((B and Archive) = Archive) then
  152.       S[4] := 'A';
  153.    FileAttribs := S;
  154. end; {FileAttribs}
  155.  
  156. function LongName(Info: tFileInfo):string;
  157. {}
  158. var 
  159.   DT :datetime;
  160.   S: String;
  161. begin
  162.    S := padleft(Info.FileName,12,' ');
  163.    UnPackTime(Info.Time,DT);
  164.    if Subdirectory(Info.Attr) then                  {add file size}
  165.       S := S + Padright('<DIR>',8,' ')
  166.    else
  167.       S := S + Padright(InttoStr(Info.Size),8,' ');
  168.    S := S + ' ';
  169.    with DT do
  170.    begin
  171.       Case Month of        
  172.          1 : S := S + 'Jan ';
  173.          2 : S := S + 'Feb ';
  174.          3 : S := S + 'Mar ';
  175.          4 : S := S + 'Apr ';
  176.          5 : S := S + 'May ';
  177.          6 : S := S + 'Jun ';
  178.          7 : S := S + 'Jul ';
  179.          8 : S := S + 'Aug ';
  180.          9 : S := S + 'Sep ';
  181.          10: S := S + 'Oct ';
  182.          11: S := S + 'Nov ';
  183.          12: S := S + 'Dec ';
  184.       end; {case}
  185.       S := S + Padright(InttoStr(Day),2,'0')+','+IntToStr(Year)+' ';
  186.       if Hour > 12 then
  187.          S := S + Padright(IntToStr(Hour-12),2,' ')+':'+Padright(IntToStr(min),2,'0')+'p'
  188.       else
  189.          S := S + Padright(IntToStr(Hour),2,' ')+':'+Padright(IntToStr(min),2,'0')+'a';
  190.       S := S + ' '+FileAttribs(Info.Attr);
  191.    end;
  192.    LongName := S;
  193. end; {LongName}
  194. {||||||||||||||||||||||||||||||||||||||||||||||}
  195. {                                              }
  196. {     D L L  N o d e O b j   M E T H O D S     }
  197. {                                              }
  198. {||||||||||||||||||||||||||||||||||||||||||||||}
  199. procedure DLLNodeObj.FreeData;
  200. {}
  201. begin
  202.    if (vDataPtr <> Nil) and (vSize > 0) then
  203.    begin
  204.       Freemem(vDataPtr,vSize);
  205.       vDataPtr := nil;
  206.       vSize:= 0;
  207.    end;
  208. end; {DLLNodeObj.FreeData}
  209.  
  210. function DLLNodeObj.NextPtr: DLLNodePtr;
  211. {}
  212. begin
  213.    NextPtr := vNextPtr;
  214. end; {DLLNodeOBJ.NextPtr}
  215.  
  216. function DLLNodeObj.PrevPtr: DLLNodePtr;
  217. {}
  218. begin
  219.    PrevPtr := vPrevPtr;
  220. end; {DLLNodeOBJ.PrevPtr}
  221.  
  222. function DLLNodeObj.GetStatus(BitPos:byte): boolean;
  223. {}
  224. var TestByte: Byte;
  225. begin
  226.    if BitPos > 7 then
  227.       GetStatus := false
  228.    else
  229.    begin
  230.      Testbyte := vStatus;
  231.      TestByte := TestByte SHR BitPos; {move to end bit}
  232.      GetStatus := odd(TestByte);
  233.    end;
  234. end; {DLLNodeOBJ.GetStatus}
  235.  
  236. procedure DLLNodeObj.SetStatus(BitPos:byte; On:boolean);
  237. {}
  238. var
  239.    Test : integer;
  240. begin
  241.    if BitPos <= 7 then
  242.    begin
  243.       if On then
  244.       begin
  245.          Test := 1 SHL BitPos;
  246.          vStatus := vStatus or Test
  247.       end
  248.       else
  249.       begin
  250.          Test := not (1 SHL BitPos);
  251.          vStatus := vStatus and Test;
  252.       end;
  253.    end;
  254. end; { DLLNodeObj.SetStatus }
  255.  
  256. function DLLNodeObj.GetStatusByte: byte;
  257. {}
  258. begin
  259.    GetStatusByte := vStatus;
  260. end; {DLLNodeObj.GetStatusByte}
  261.  
  262. procedure DLLNodeObj.SetStatusByte(Val:byte);
  263. {}
  264. begin
  265.    vStatus := Val;
  266. end; {DLLNodeObj.SetStatusByte}
  267. {|||||||||||||||||||||||||||||||||||||}
  268. {                                     }
  269. {     D L L O b j   M E T H O D S     }
  270. {                                     }
  271. {|||||||||||||||||||||||||||||||||||||}
  272. constructor DLLOBJ.Init;
  273. {}
  274. begin
  275.    vStartNodePtr := nil;
  276.    vEndNodePtr := nil;
  277.    vActiveNodePtr := nil;
  278.    vTotalNodes := 0;
  279.    vActiveNodeNumber := 0;
  280.    vSortID := 0;
  281.    vSortAscending := true;
  282.    vSorted := true;
  283.    vMaxNodeSize := 0;
  284. end; {DLLOBJ.Init}
  285.  
  286. function DLLOBJ.Add(var TheData; Size:Longint): integer;
  287. { Adds node after the ActiveNodePtr, and increments the
  288.   ActiveNodePtr.
  289.  
  290.   Returns status indicating result of attemp to add.
  291.   Codes:          0      Success
  292.                   1      Not enough memory
  293.                   2      Not enough memory for data
  294. }
  295. var
  296.   Temp: DLLNodePtr;
  297. begin
  298.    if MaxAvail < sizeOf(vStartNodePtr^) then
  299.    begin
  300.       Add := 1;  {not enough memory}
  301.       exit;
  302.    end;
  303.    if vStartNodePtr = nil then
  304.    begin
  305.       getmem(vStartNodePtr,sizeof(vStartNodePtr^));
  306.       vStartNodePtr^.vPrevPtr := nil;
  307.       vActiveNodePtr := vStartNodePtr;
  308.       vActiveNodePtr^.vNextPtr := nil;
  309.       vActiveNodeNumber := 1;
  310.       vEndNodePtr := vActiveNodePtr;
  311.    end
  312.    else
  313.    begin
  314.       if vActiveNodePtr^.vNextPtr = nil then
  315.       begin
  316.          getmem(vActiveNodePtr^.vNextPtr,sizeof(vActiveNodePtr^));
  317.          vActiveNodePtr^.vNextPtr^.vPrevPtr := vActiveNodePtr;
  318.          vActiveNodePtr := vActiveNodePtr^.vNextPtr;
  319.          vActiveNodePtr^.vNextPtr := nil;
  320.          inc(vActiveNodeNumber);
  321.          vEndNodePtr := vActiveNodePtr;
  322.       end
  323.       else  {insert a node}
  324.       begin
  325.          getmem(Temp,sizeof(temp^));
  326.          vActiveNodePtr^.vNextPtr^.vPrevPtr := Temp;
  327.          Temp^.vNextPtr := vActiveNodePtr^.vNextPtr;
  328.          Temp^.vPrevPtr := vActiveNodePtr;
  329.          vActiveNodePtr^.vNextPtr := Temp;
  330.          vActiveNodePtr := Temp;
  331.          inc(vActiveNodeNumber);
  332.       end;
  333.    end;
  334.    inc(vTotalNodes);
  335.    {now add the data to the node data pointer}
  336.    if MemAvail < Size then
  337.    begin
  338.      Add := 2;   {not enough memory for data}
  339.      vActiveNodePtr^.vSize := 0;
  340.      vActiveNodePtr^.vDataPtr := nil;
  341.      exit;
  342.    end;
  343.    if Size > 0 then
  344.    begin
  345.       getmem(vActiveNodePtr^.vDataPtr,Size);
  346.       move(TheData,vActiveNodePtr^.vDataPtr^,Size);
  347.       if Size > vMaxNodeSize then
  348.          vMaxNodeSize := Size;
  349.    end
  350.    else
  351.       vActiveNodePtr^.vDataPtr := nil;
  352.    vActiveNodePtr^.vSize := Size;
  353.    vActiveNodePtr^.vStatus := 0;
  354.    Add := 0;
  355. end; {DLLOBJ.Add}
  356.  
  357. function DLLOBJ.Change(Node:DLLNodePtr;var TheData; Size:Longint): integer;
  358. { Returns status indicating result of attemp to add.
  359.   Codes:          0      Success
  360.                   2      Not enough memory for data
  361.                   3      Invalid Node Ptr
  362. }
  363. begin
  364.    if node = nil then
  365.       Change := 3
  366.    else 
  367.    begin
  368.      Node^.FreeData;
  369.      if MaxAvail < Size then
  370.         Change := 2
  371.      else
  372.      begin
  373.          Change := 0;
  374.          getmem(Node^.vDataPtr,Size);
  375.          move(TheData,Node^.vDataPtr^,Size);
  376.          Node^.vSize := Size;
  377.      end;
  378.    end;
  379. end; {DLLOBJ.Change}
  380.  
  381. function DLLOBJ.InsertBefore(Node:DLLNodePtr;var TheData;Size:longint): integer;
  382. { Returns status indicating result of attemp to add.
  383.   Codes:          0      Success
  384.                   1      Not enough memory
  385.                   2      Not enough memory for data
  386.                   3      Invalid Node Ptr
  387. }
  388. var
  389.   Temp: DLLNodePtr;
  390. begin
  391.    if node = nil then
  392.       InsertBefore := 3
  393.    else if MaxAvail < sizeOf(Node^) then
  394.       InsertBefore:= 1  {not enough memory}
  395.    else
  396.    begin
  397.       if Node = vStartNodePtr then {add to head of list}
  398.       begin
  399.          getmem(Node^.vPrevPtr,sizeof(Node^));
  400.          Node^.vPrevPtr^.vNextPtr := Node;
  401.          Node := Node^.vPrevPtr;
  402.          Node^.vPrevPtr := nil;
  403.          vStartNodePtr := Node;
  404.       end
  405.       else
  406.       begin
  407.          getmem(Temp,sizeof(Temp^));
  408.          Node^.vPrevPtr^.vNextPtr := Temp;
  409.          Temp^.vPrevPtr := Node^.PrevPtr;
  410.          Node^.vPrevPtr := Temp;
  411.          Temp^.vNextPtr := Node;
  412.          Node := Temp;
  413.       end;
  414.       inc(vTotalNodes);
  415.       vActiveNodeNumber := 1;
  416.       vActiveNodePtr := vStartNodePtr;
  417.       if MemAvail < Size then
  418.       begin
  419.          InsertBefore := 2;   {not enough memory for data}
  420.          Node^.vSize := 0;
  421.          Node^.vDataPtr := nil;
  422.       end
  423.       else
  424.       begin
  425.          if Size > 0 then
  426.          begin
  427.             getmem(Node^.vDataPtr,Size);
  428.             move(TheData,Node^.vDataPtr^,Size);
  429.          end
  430.          else
  431.            Node^.vDataPtr := nil;
  432.          Node^.vSize := Size;
  433.          InsertBefore := 0;
  434.       end;
  435.    end;
  436. end; {DLLOBJ.InsertBefore}
  437.  
  438. procedure DLLOBJ.Get(Var TheData);
  439. {}
  440. begin
  441.     with vActiveNodePtr^ do
  442.        if vDataPtr <> Nil then
  443.           move(vDataPtr^,TheData,vSize);
  444. end; {DLLOBJ.Get}
  445.  
  446. procedure DLLOBJ.GetNodeData(Node:DLLNodePtr;Var TheData);
  447. {}
  448. begin
  449.     with Node^ do
  450.        if vDataPtr <> Nil then
  451.           move(vDataPtr^,TheData,vSize);
  452. end; {DLLOBJ.GetNodedata}
  453.  
  454. function DLLOBJ.GetNodeDataSize(Node:DLLNodePtr):longint;
  455. {}
  456. begin
  457.    with Node^ do
  458.    begin
  459.       if vDataPtr = Nil then
  460.          GetNodeDataSize := 0
  461.       else
  462.          GetNodeDataSize := vSize;
  463.    end;
  464. end; {DLLOBJ.GetNodeDataSize}
  465.  
  466. function DLLOBJ.GetMaxNodeSize: longint;
  467. {}
  468. begin
  469.    GetMaxNodeSize := vMaxNodeSize;
  470. end; {DLLOBJ.GetMaxNodeSize}
  471.  
  472. function DLLOBJ.GetStr(Node:DLLNodePtr;Start,Finish:longint): String;
  473. {generic method..usually in descendant object}
  474. var temp: string;
  475. begin
  476.    if Start < 0 then Start := 0;
  477.    if Finish < 0 then Finish := 0;
  478.    {validate Start and Finish Parameters}
  479.    if ((Finish = 0) and (Start = 0))
  480.    or (Start > Finish) then   {get full string}
  481.    begin
  482.       Start := 1;
  483.       Finish := 255;
  484.    end
  485.    else if Finish - Start > 254 then      {too long to fit in string}
  486.       Finish := Start + 254;
  487.  
  488.    if (Node = Nil)
  489.    or (Node^.vDataPtr = Nil)
  490.    or (Node^.vSize = 0)
  491.    or (Start > Node^.vSize) then
  492.       GetStr := ''
  493.    else
  494.    begin
  495.       if Finish > Node^.vSize then
  496.          Finish := Node^.vSize;
  497.       if Start = 0 then
  498.          inc(Start);
  499.       Move(mem[seg(Node^.vDataPtr^):ofs(Node^.vDataPtr^)+pred(Start)],Temp[1],succ(Finish-Start));
  500.       Temp [0] := chr(succ(Finish-Start));
  501.       GetStr := Temp;
  502.    end;
  503. end; {DLLOBJ.GetStr}
  504.  
  505. procedure DLLOBJ.Advance(Amount:longint);
  506. {}
  507. var
  508.   I : longint;
  509. begin
  510.    for I := 1 to Amount do
  511.       if vActiveNodePtr^.vNextPtr <> nil then
  512.       begin
  513.           vActiveNodePtr := vActiveNodePtr^.vNextPtr;
  514.           inc(vActiveNodeNumber);
  515.       end;
  516. end; {DLLOBJ.Advance}
  517.  
  518. procedure DLLOBJ.Retreat(Amount:longint);
  519. {}
  520. var
  521.   I : longint;
  522. begin
  523.    for I := 1 to Amount do
  524.       if vActiveNodePtr^.vPrevPtr <> nil then
  525.       begin
  526.           vActiveNodePtr := vActiveNodePtr^.vPrevPtr;
  527.           dec(vActiveNodeNumber);
  528.       end;
  529. end; {DLLOBJ.Retreat}
  530.  
  531. procedure DLLOBJ.Jump(NodeNumber:longint);
  532. {}
  533. begin
  534.    if NodeNumber = 1 then
  535.    begin
  536.       vActiveNodePtr := vStartNodePtr;
  537.       vActiveNodeNumber := 1;
  538.    end
  539.    else
  540.    begin
  541.       if NodeNumber < vActiveNodeNumber then
  542.          Retreat(vActiveNodeNumber - NodeNumber)
  543.       else
  544.          Advance(NodeNumber - vActiveNodeNumber);
  545.    end;
  546. end; {DLLOBJ.Jump}
  547.  
  548. procedure DLLOBJ.ShiftActiveNode(NewNode: DLLNodePtr; NodeNumber: longint);
  549. {}
  550. begin
  551.    vActiveNodePtr := NewNode;
  552.    vActiveNodeNumber := NodeNumber;
  553. end; {DLLOBJ.ShiftActiveNode}
  554.  
  555. function DLLOBJ.NodePtr(NodeNumber:longint): DLLNodePtr;
  556. {}
  557. var
  558.   StartNode: DLLNodePtr;
  559.   DistanceA,
  560.   DistanceB,
  561.   DistanceC,
  562.   Counter,
  563.   I: LongInt;
  564.   Forwards : boolean;
  565.   Indicator : byte;
  566. begin
  567.    if (NodeNumber < 1) or (NodeNumber > vTotalNodes) then
  568.       NodePtr := nil
  569.    else
  570.    begin
  571.       if NodeNumber = 1 then
  572.          NodePtr := vStartNodePtr
  573.       else if NodeNumber = vTotalNodes then
  574.             NodePtr := vEndNodePtr
  575.       else if NodeNumber = vActiveNodeNumber then
  576.             NodePtr := vActiveNodePtr
  577.       else
  578.       begin
  579.          {check for the nearest node ptr, and jump from there}
  580.          DistanceA := abs(NodeNumber - vActiveNodeNumber);
  581.          DistanceB := NodeNumber;
  582.          DistanceC := vTotalNodes - NodeNumber;
  583.          if DistanceA < DistanceB then
  584.          begin
  585.             if DistanceA < DistanceC then
  586.             begin
  587.                StartNode := vActiveNodePtr;
  588.                Forwards := (vActiveNodeNumber < NodeNumber);
  589.                Counter := DistanceA;
  590.             end
  591.             else
  592.             begin
  593.                StartNode := vEndNodePtr;
  594.                Forwards := false;
  595.                Counter := DistanceC;
  596.             end;
  597.          end
  598.          else      {DA > DB}
  599.          begin
  600.             if DistanceB < DistanceC then
  601.             begin
  602.                StartNode := vStartNodePtr;
  603.                Forwards := true;
  604.                Counter := pred(DistanceB);
  605.             end
  606.             else
  607.             begin
  608.                StartNode := vEndNodePtr;
  609.                Forwards := false;
  610.                Counter := DistanceC;
  611.             end;
  612.          end;
  613.          if Forwards then
  614.             for I := 1 to Counter do
  615.                 StartNode := StartNode^.NextPtr
  616.          else
  617.             for I := 1 to Counter do
  618.                 StartNode := StartNode^.PrevPtr;
  619.          NodePtr := StartNode;
  620.  
  621.       end;
  622.   end;
  623. end; {DLLOBJ.NodePtr}
  624.  
  625. function DLLOBJ.TotalNodes: longint;
  626. {}
  627. begin
  628.     TotalNodes := vTotalNodes;
  629. end;
  630.  
  631. function DLLOBJ.ActiveNodeNumber: longint;
  632. {}
  633. begin
  634.     ActiveNodeNumber := vActiveNodeNumber;
  635. end;
  636.  
  637. function DLLOBJ.StartNodePtr: DLLNodePtr;
  638. {}
  639. begin
  640.    StartNodePtr := vStartNodePtr;
  641. end; {DLLOBJ.StartNodePtr}
  642.  
  643. function DLLOBJ.EndNodePtr: DLLNodePtr;
  644. {}
  645. begin
  646.    EndNodePtr := vEndNodePtr;
  647. end; {DLLOBJ.EndNodePtr}
  648.  
  649. function DLLOBJ.ActiveNodePtr: DLLNodePtr;
  650. {}
  651. begin
  652.     ActiveNodePtr := vActiveNodePtr;
  653. end; {DLLOBJ.ActiveNodePtr}
  654.  
  655. (* The following procedure requires only 8 bytes on the 
  656.    stack but damn it's slow!
  657. procedure DLLOBJ.SwapNodes(Node1,Node2:DLLNodePtr);
  658. {swaps the position of two nodes in the tree}
  659. var
  660.    TempPrevPtr,
  661.    TempNextPtr : DLLNodePtr;
  662. begin
  663.    if vStartNodePtr = Node1 then
  664.       vStartNodePtr := Node2
  665.    else if vStartNodePtr = Node2 then
  666.       vStartNodePtr := Node1;
  667.    if vEndNodePtr = Node1 then
  668.       vEndNodePtr := Node2
  669.    else if vEndNodePtr = Node2 then
  670.       vEndNodePtr := Node1;
  671.    if vActiveNodePtr = Node1 then
  672.       vActiveNodePtr := Node2
  673.    else if vActiveNodePtr = Node2 then
  674.       vActiveNodePtr := Node1;
  675.    if (Node1^.vNextPtr = Node2) then  {nodes next to each other}
  676.    begin
  677.       TempNextPtr := Node2^.vNextPtr;
  678.       {move Node2 into Node1's place}
  679.       Node2^.vPrevPtr := Node1^.vPrevPtr;
  680.       Node2^.vNextPtr := Node1;
  681.       if Node2^.vPrevPtr <> nil then
  682.          Node2^.vPrevPtr^.vNextPtr := Node2;
  683.       if Node2^.vNextPtr <> nil then
  684.          Node2^.vNextPtr^.vPrevPtr := Node2;
  685.       {move Node1 into Node2's place}
  686.       Node1^.vPrevPtr := Node2;
  687.       Node1^.vNextPtr := TempNextPtr;
  688.       if Node1^.vNextPtr <> nil then
  689.          Node1^.vNextPtr^.vPrevPtr := Node1;
  690.    end
  691.    else
  692.       if (Node1^.vPrevPtr = Node2) then  {nodes next to each other}
  693.       begin
  694.          TempPrevPtr := Node2^.vPrevPtr;
  695.          {move Node2 into Node1's place}
  696.          Node2^.vPrevPtr := Node1;
  697.          Node2^.vNextPtr := Node1^.vNextPtr;
  698.          if Node2^.vNextPtr <> nil then
  699.             Node2^.vNextPtr^.vPrevPtr := Node2;
  700.          {move Node1 into Node2's place}
  701.          Node1^.vPrevPtr := TempPrevPtr;
  702.          Node1^.vNextPtr := Node2;
  703.          if Node1^.vPrevPtr <> nil then
  704.             Node1^.vPrevPtr^.vNextPtr := Node1;
  705.       end
  706.       else  {the nodes are not adjacent to each other}
  707.       begin
  708.          TempPrevPtr := Node2^.vPrevPtr;
  709.          TempNextPtr := Node2^.vNextPtr;
  710.          {move Node2 into Node1's place}
  711.          Node2^.vPrevPtr := Node1^.vPrevPtr;
  712.          Node2^.vNextPtr := Node1^.vNextPtr;
  713.          if Node2^.vPrevPtr <> nil then
  714.             Node2^.vPrevPtr^.vNextPtr := Node2;
  715.          if Node2^.vNextPtr <> nil then
  716.             Node2^.vNextPtr^.vPrevPtr := Node2;
  717.          {move Node1 into Node2's place}
  718.          Node1^.vPrevPtr := TempPrevPtr;
  719.          Node1^.vNextPtr := TempNextPtr;
  720.          if Node1^.vPrevPtr <> nil then
  721.             Node1^.vPrevPtr^.vNextPtr := Node1;
  722.          if Node1^.vNextPtr <> nil then
  723.             Node1^.vNextPtr^.vPrevPtr := Node1;
  724.       end;
  725. end; {DLLOBJ.SwapNodes}
  726. *)
  727.  
  728. procedure DLLOBJ.SwapNodes(Node1,Node2:DLLNodePtr);
  729. {}
  730. var 
  731.   Ptr1: pointer;
  732.   Size1,Size2: longint;
  733.   Status1: byte;
  734.   Ecode: integer;
  735. begin
  736.    Status1 := Node1^.GetStatusByte;
  737.    Node1^.SetStatusByte(Node2^.GetStatusByte);
  738.    Node2^.SetStatusByte(Status1);
  739.    Size1 := GetNodeDataSize(Node1);
  740.    if Size1 > 0 then
  741.    begin
  742.       getmem(Ptr1,size1);
  743.       GetNodeData(Node1,Ptr1^);
  744.    end;
  745.    Size2 := GetNodeDataSize(Node2);
  746.    Ecode := Change(Node1,Node2^.vDataPtr^,Size2);
  747.    Ecode := Change(Node2,Ptr1^,Size1);
  748.    if Size1 > 0 then
  749.       freemem(Ptr1,Size1);
  750. end; {DLLOBJ.SwapNodes}
  751.  
  752. procedure DLLOBJ.DelNode(Node: DLLNodePtr);
  753. {}
  754. begin
  755.    if vActiveNodePtr = Node then   {move active ptr to next entry in list}
  756.    begin
  757.       if vActiveNodePtr^.vNextPtr = nil then
  758.       begin
  759.          dec(vActiveNodeNumber);
  760.          vActiveNodePtr := vActiveNodePtr^.vPrevPtr;
  761.       end
  762.       else
  763.          vActiveNodePtr := vActiveNodePtr^.vNextPtr;
  764.    end;
  765.    if Node = vStartNodePtr then
  766.    begin
  767.       if Node^.vNextPtr = nil then {only node in list}
  768.       begin
  769.          Node^.FreeData;
  770.          Freemem(vStartNodePtr,sizeof(vStartNodePtr^));
  771.          vStartNodePtr := nil;
  772.          vEndNodePtr := nil;
  773.       end
  774.       else
  775.       begin
  776.          vStartNodePtr := vStartNodePtr^.vNextPtr;
  777.          vStartNodePtr^.vPrevPtr := nil;
  778.          Node^.FreeData;
  779.          Freemem(Node,sizeof(Node^));
  780.       end;
  781.    end
  782.    else
  783.    begin
  784.       Node^.vPrevPtr^.vNextPtr := Node^.vNextPtr;
  785.       if Node = vEndNodePtr then
  786.          vEndNodePtr := vEndNodePtr^.vPrevPtr
  787.       else
  788.          Node^.vNextPtr^.vPrevPtr := Node^.vPrevPtr;
  789.       Node^.FreeData;
  790.       Freemem(Node,sizeof(Node^));
  791.    end;
  792.    dec(vTotalNodes);
  793. end; {DLLOBJ.DelNode}
  794.  
  795. procedure DLLOBJ.DelAllStatus(BitPos:byte;On:boolean);
  796. {}
  797. var
  798.   TempPtr,TempNextPtr: DLLNodePtr;
  799. begin
  800.    if vStartNodePtr <> nil then
  801.    begin
  802.       TempPtr := vStartNodePtr;
  803.       TempNextPtr := TempPtr^.NextPtr;
  804.       while TempNextPtr <> nil do
  805.       begin
  806.          if TempNextPtr^.GetStatus(BitPos) = On then
  807.             DelNode(TempNextPtr)
  808.          else
  809.             TempPtr := TempPtr^.NextPtr;
  810.             TempNextPtr := TempPtr^.NextPtr;
  811.       end;
  812.        if vStartNodePtr^.GetStatus(BitPos) = On then
  813.             DelNode(vStartNodePtr)
  814.    end;
  815. end; {DLLOBJ.DelAllStatus}
  816.  
  817. function DLLOBJ.WrongOrder(Node1,Node2:DLLNodePtr;Asc:boolean):boolean;
  818. {abstract}
  819. begin
  820.    WrongOrder := false;
  821. end; {DLLOBJ.WrongOrder}
  822.  
  823. procedure DLLOBJ.Sort(SortID:shortint;Ascending:boolean);
  824. {Shell sort}
  825. var
  826.    I,J,Delta : longint;
  827.    Swapped : boolean;
  828.    Ptr1,Ptr2 : DLLNodePtr;
  829. begin
  830.    if ((vSortID <> SortID) or (vSortAscending <> Ascending) or (vSorted = false))
  831.    and (vTotalNodes >= 2) then
  832.    begin
  833.       vSortID := SortID;
  834.       vSortAscending := Ascending;
  835.       Delta := vTotalNodes div 2;
  836.       repeat
  837.          Repeat
  838.             Swapped := false;
  839.             Ptr1 := vStartNodePtr;
  840.             Ptr2 := Ptr1;
  841.             for I := 1 to Delta do
  842.               Ptr2 := Ptr2^.vNextPtr;
  843.             for I := 1 to vTotalNodes - Delta do
  844.             begin
  845.               if I > 1 then
  846.               begin
  847.                  Ptr1 := Ptr1^.vNextPtr;
  848.                  Ptr2 := Ptr2^.vNextPtr;
  849.               end;
  850.               if WrongOrder(Ptr1,Ptr2,vSortAscending) then
  851.               begin
  852.                  SwapNodes(Ptr1,Ptr2);
  853.                  Swapped := true;
  854.               end;
  855.             end;
  856.          Until (not Swapped);
  857.          Delta := Delta div 2;
  858.       Until Delta = 0;
  859.    end;
  860.    vSorted := true;
  861. end; {DLLOBJ.Sort}
  862.  
  863. procedure DLLOBJ.EmptyList;
  864. {removes all the memory allocated on the heap by chaining back
  865.  through the list and disposing of each node.}
  866. var TempPtr: DLLNodePtr;
  867. begin
  868.    TempPtr := vEndNodePtr;
  869.    if vEndNodePtr <> nil then
  870.    while TempPtr^.vPrevPtr <> nil do
  871.    begin
  872.       TempPtr^.FreeData;
  873.       TempPtr := TempPtr^.vPrevPtr;
  874.       Freemem(TempPtr^.vNextPtr,sizeof(TempPtr^));
  875.    end;
  876.    if vStartNodePtr <> Nil then
  877.    begin
  878.       vStartNodePtr^.FreeData;
  879.       Freemem(vStartNodePtr,sizeof(vStartNodePtr^));
  880.       vStartNodePtr := Nil;
  881.    end;
  882.    vEndNodePtr := nil;
  883.    vActiveNodePtr := nil;
  884.    vTotalNodes := 0;
  885.    vActiveNodeNumber := 0;
  886. end; {DLLOBJ.EmptyList}
  887.  
  888. destructor DLLOBJ.Done;
  889. {}
  890. begin
  891.    EmptyList;
  892. end; {of dest DLLOBJ.Done}
  893.  
  894. {|||||||||||||||||||||||||||||||||||||||||||}
  895. {                                           }
  896. {     S t r D L L O b j   M E T H O D S     }
  897. {                                           }
  898. {|||||||||||||||||||||||||||||||||||||||||||}
  899.  
  900. {The StrDLLOBJ object is a descendant of the DLLOBJ object, and
  901.  it is designed to specifically manipulate strings}
  902.  
  903. constructor StrDLLOBJ.Init;
  904. {}
  905. begin
  906.    DLLOBJ.Init;
  907. end; {StrDLLOBJ.Init}
  908.  
  909. function StrDLLOBJ.Add(Str: string): integer;
  910. {}
  911. var
  912.   Len : byte;
  913. begin
  914.    Len := Length(Str);
  915.    Add := DLLOBJ.Add(Str[1],Len);
  916. end; {StrDLLOBJ.Add}
  917.  
  918. function StrDLLOBJ.GetStr(Node:DLLNodePtr;Start,Finish:longint): String;
  919. {}
  920. begin
  921.    GetStr := DLLOBJ.GetStr(Node,Start,Finish);
  922. end; {StrDLLOBJ.GetStr}
  923.  
  924. function StrDLLOBJ.Change(Node:DLLNodePtr;Str: string): integer;
  925. {}
  926. var
  927.   Len:byte;
  928. begin
  929.    Len := length(Str);
  930.    Change := DLLOBJ.Change(Node,Str[1],Len);
  931. end; {StrDLLOBJ.Change}
  932.  
  933. function StrDLLOBJ.InsertBefore(Node:DLLNodePtr;Str:string): integer;
  934. {}
  935. var
  936.   Len:byte;
  937. begin
  938.    Len := length(Str);
  939.    InsertBefore := DLLOBJ.InsertBefore(Node,Str[1],Len);
  940. end; {StrDLLOBJ.InsertBefore}
  941.  
  942. function StrDLLOBJ.WrongOrder(Node1,Node2:DLLNodePtr;Asc:boolean): boolean;
  943. {}
  944. var S1,S2: string;
  945. begin
  946. (*
  947.    if Asc then
  948.    begin
  949.       GetNodeData(Node1,S1);
  950.       GetNodeData(Node2,S2);
  951.    end
  952.    else
  953.    begin
  954.       GetNodeData(Node1,S2);
  955.       GetNodeData(Node2,S1);
  956.    end;
  957. *)
  958.    if Asc then
  959.    begin
  960.       S1 := GetStr(Node1,1,255);
  961.       S2 := GetStr(Node2,1,255);
  962.    end
  963.    else
  964.    begin
  965.       S1 := GetStr(Node2,1,255);
  966.       S2 := GetStr(Node1,1,255);
  967.    end;
  968.    WrongOrder := (S1 > S2);
  969. end; {StrDLLOBJ.WrongOrder}
  970.  
  971. destructor StrDLLOBJ.Done;
  972. {}
  973. begin
  974.    DLLOBJ.Done;
  975. end; {StrDLLOBJ.Done}
  976. {|||||||||||||||||||||||||||||||||||||||||||||}
  977. {                                             }
  978. {     F i l e D L L O b j   M E T H O D S     }
  979. {                                             }
  980. {|||||||||||||||||||||||||||||||||||||||||||||}
  981. constructor FileDLLOBJ.Init;
  982. {}
  983. begin
  984.    DLLOBJ.Init;
  985.    vFileMasks := '*.*';
  986.    vFileAttrib := archive + readonly;
  987. end; {FileDLLOBJ.Init}
  988.  
  989. function FileDLLOBJ.GetStr(Node:DLLNodePtr;Start,Finish: longint):string; 
  990. {ignores Start and Finish parameters - first 13 bytes of the Data is
  991.  the filename.}
  992. var temp : string;
  993. begin
  994.    if (Node = Nil)
  995.    or (Node^.vDataPtr = Nil)
  996.    or (Node^.vSize = 0)  then
  997.       GetStr := ''
  998.    else
  999.    begin
  1000.       Move(mem[seg(Node^.vDataPtr^):ofs(Node^.vDataPtr^)],Temp[0],13);
  1001.       GetStr := Temp;
  1002.    end;
  1003. end; {FileDLLOBJ.GetStr}
  1004.  
  1005. function FileDLLOBJ.GetLongStr(Node:DLLNodePtr):string;
  1006. {}
  1007. var Info: tFileInfo;
  1008. begin
  1009.    if (Node = Nil)
  1010.    or (Node^.vDataPtr = Nil)
  1011.    or (Node^.vSize = 0)  then
  1012.       GetLongStr := ''
  1013.    else
  1014.    begin
  1015.       Move(mem[seg(Node^.vDataPtr^):ofs(Node^.vDataPtr^)],Info,sizeof(Info));
  1016.       if Info.FileName = NoFiles then
  1017.          GetLongStr := 'No matching files found'
  1018.       else
  1019.          GetLongStr := LongName(Info);
  1020.    end;
  1021. end; {FileDLLOBJ.GetLongStr}
  1022.  
  1023. procedure FileDLLOBJ.GetFileRecord(var FileInfo:tFileInfo; Item:longint);
  1024. {}
  1025. var
  1026.    Node:DLLNodePtr;
  1027. begin
  1028.    Node := NodePtr(Item);
  1029.    if (Node = Nil)
  1030.    or (Node^.vDataPtr = Nil)
  1031.    or (Node^.vSize = 0)  then
  1032.       FileInfo.FileName := ''
  1033.    else
  1034.       Move(mem[seg(Node^.vDataPtr^):ofs(Node^.vDataPtr^)],FileInfo,sizeof(FileInfo));
  1035. end; {FileDLLOBJ.GetFileRecord}
  1036.  
  1037. function FileDLLOBJ.GetFileMask:string;
  1038. {}
  1039. begin
  1040.    GetFileMask := vFileMasks;
  1041. end; {FileDLLOBJ.GetFileMask}
  1042.  
  1043. procedure FileDLLOBJ.SetFileDetails(FileMasks:string; FileAttrib: word);
  1044. {}
  1045. begin
  1046.    if FileMasks = '' then
  1047.       FileMasks := '*.*';
  1048.    vFileMasks := FileMasks;
  1049.    vFileAttrib := FileAttrib;
  1050. end; {FileDLLOBJ.SetFileDetails}
  1051.  
  1052. procedure FileDLLOBJ.FillList;
  1053. {}
  1054. var
  1055.   FileDetails: SearchRec;
  1056.   FileInfo: tFileInfo;
  1057.   TotMasks: byte;
  1058.   Mask: string;
  1059.   RecSize: byte;
  1060.   ECode : integer;
  1061.  
  1062.   procedure SaveFileDetails(IsDir:boolean);
  1063.   begin
  1064.      if FileDetails.Name <> '.' then
  1065.      begin
  1066.         with FileInfo do
  1067.         begin
  1068.             FileName := FileDetails.Name;
  1069.             Attr := FileDetails.Attr;
  1070.             Time := FileDetails.Time;
  1071.             Size := FileDetails.Size;
  1072.             LoadID := succ(vTotalNodes);
  1073.         end;  {with}
  1074.         Ecode := Add(FileInfo,RecSize);
  1075.         if Ecode = 0 then
  1076.           vActiveNodePtr^.SetStatus(1,IsDir);
  1077.      end;
  1078.   end; {SaveFileDetails}
  1079.  
  1080.   procedure ProcessFiles(Attrib:word);
  1081.   {}
  1082.   var I : integer;
  1083.   begin
  1084.      for I := 1 to TotMasks do
  1085.      begin
  1086.         Mask := ExtractWords(I,1,vFileMasks);
  1087.         FindFirst(Mask,Attrib,FileDetails);
  1088.         while DOSError = 0 do
  1089.         begin
  1090.            if (Attrib <> Directory) then
  1091.               SaveFileDetails(false)
  1092.            else if ((Attrib = Directory) and (FileDetails.Attr = Directory)) then
  1093.               SaveFileDetails(true);
  1094.            FindNext(FileDetails);
  1095.         end;
  1096.      end;
  1097.   end; {ProcessFiles}
  1098.  
  1099. begin
  1100.    RecSize := sizeof(FileInfo);
  1101.    if vStartNodePtr <> Nil then
  1102.       EmptyList;
  1103.    TotMasks := WordCnt(vFilemasks);
  1104.    if ((vFileAttrib and Directory) = Directory) then
  1105.    begin
  1106.       ProcessFiles(Directory);
  1107.       ProcessFiles(vFileAttrib and (Anyfile-Directory-VolumeID));
  1108.    end
  1109.    else
  1110.       ProcessFiles(vFileAttrib);
  1111.    if vTotalNodes = 0 then
  1112.    begin
  1113.       FileInfo.Filename := NoFiles;
  1114.       FileInfo.Time := 0;
  1115.       Ecode := Add(FileInfo,RecSize);
  1116.    end;
  1117.    vSorted := (vSortID = 0) and (vSortAscending = true);
  1118. end; {FileDLLOBJ.FillList}
  1119.  
  1120. procedure FileDLLOBJ.FillNewMask(FileMasks:string);
  1121. {}
  1122. begin
  1123.    SetFileDetails(FileMasks,vFileAttrib);
  1124.    FillList;
  1125. end; {FileDLLOBJ.FillNewMask}
  1126.  
  1127. function FileDLLOBJ.WrongOrder(Node1,Node2:DLLNodePtr;Asc:boolean): boolean;
  1128. {}
  1129. var F1,F2: tFileInfo;
  1130.     P: integer;
  1131.     Name1,Name2: string[8];
  1132.     Ext1,Ext2: string[3];
  1133.  
  1134.     function Name(F:tFileInfo):string;
  1135.     {}
  1136.     begin
  1137.        P := pos('.',F.FileName);
  1138.        if P = 0 then
  1139.           Name := F.FileName
  1140.        else
  1141.           Name := copy(F.FileName,1,pred(P));
  1142.     end;{Name}
  1143.  
  1144.     function Ext(F:tFileInfo):string;
  1145.     {}
  1146.     begin
  1147.        P:= pos('.',F.FileName);
  1148.        if P = 0 then
  1149.           Ext := ''
  1150.        else
  1151.           Ext := copy(F.FileName,succ(P),3);
  1152.     end; {Ext}
  1153.  
  1154. begin
  1155.    fillchar(F1,sizeof(F1),#0);
  1156.    fillchar(F2,sizeof(F2),#0);
  1157.    if Asc then
  1158.    begin
  1159.       GetNodeData(Node1,F1);
  1160.       GetNodeData(Node2,F2);
  1161.    end
  1162.    else
  1163.    begin
  1164.       GetNodeData(Node1,F2);
  1165.       GetNodeData(Node2,F1);
  1166.    end;
  1167.    case vSortID of
  1168.       0: WrongOrder := (F1.LoadID > F2.LoadID);  {DOS}
  1169.       1: begin                                    {NAME}
  1170.             Name1 := Name(F1);
  1171.             Name2 := Name(F2);
  1172.             if (Name1 = Name2) then
  1173.                WrongOrder := (Ext(F1) > Ext(F2))
  1174.             else
  1175.                WrongOrder := (Name1 > Name2);
  1176.       end;
  1177.       2: begin                                    {EXT}
  1178.             Ext1 := Ext(F1);
  1179.             Ext2 := Ext(F2);
  1180.             if Ext1 = Ext2 then
  1181.                WrongOrder := (Name(F1) > Name(F2))
  1182.             else
  1183.                WrongOrder := (Ext1 > Ext2);
  1184.       end;
  1185.       3: WrongOrder := (F1.Size > F2.Size);      {SIZE}
  1186.       4: WrongOrder := (F1.Time > F2.Time);      {TIME}
  1187.       else WrongOrder := false;
  1188.    end; {case}
  1189. end; {FileDLLOBJ.WrongOrder}
  1190.  
  1191. procedure FileDLLOBJ.SwapNodes(Node1,Node2:DLLNodePtr);
  1192. {}
  1193. var 
  1194.   FileInfo: tFileInfo;
  1195.   Size: longint;
  1196.   Status1: byte;
  1197. begin
  1198.    Status1 := Node1^.GetStatusByte;
  1199.    Node1^.SetStatusByte(Node2^.GetStatusByte);
  1200.    Node2^.SetStatusByte(Status1);
  1201.    GetNodeData(Node1,FileInfo);
  1202.    Size := sizeof(FileInfo);
  1203.    Move(Node2^.vDataPtr^,Node1^.vDataPtr^,size);
  1204.    Move(FileInfo,Node2^.vDataPtr^,size);
  1205. end; {FileDLLOBJ.SwapNodes}
  1206.  
  1207. destructor FileDLLOBJ.Done;
  1208. {}
  1209. begin
  1210.    DLLOBJ.Done;
  1211. end; {FileDLLOBJ.Done}
  1212. {|||||||||||||||||||||||||||||||||||||||||||||||}
  1213. {                                               }
  1214. {     U N I T   I N I T I A L I Z A T I O N     }
  1215. {                                               }
  1216. {|||||||||||||||||||||||||||||||||||||||||||||||}
  1217. procedure LinkInit;
  1218. {initilizes objects and global variables}
  1219. begin
  1220. end;
  1221.  
  1222. {end of unit}
  1223. {$ifNDEF OVERLAY}
  1224. begin
  1225.    LINKInit;
  1226. {$ENDif}
  1227. end.
  1228.